#ifndef DW_GRAPHICS_OPENGL_BUFFER_OBJECT_H
#	define DW_GRAPHICS_OPENGL_BUFFER_OBJECT_H

#if !(DW_GRAPHICS_BACKEND_OPENGL)
#	error "Invalid included file"
#endif // !(DW_GRAPHICS_BACKEND_OPENGL)

#include "system/buffer.h"

namespace dw {
	namespace graphics {
		namespace details {

// http://www.opengl.org/sdk/docs/man4/xhtml/glBindBuffer.xml
// Plein de bindings possible pour le meme type en fonction de ce qu'on veut faire : GL_PIXEL_PACK_BUFFER and GL_PIXEL_UNPACK_BUFFER   GL_COPY_READ_BUFFER and GL_COPY_WRITE_BUFFER

class BufferObject
:	public dw::system::Buffer
{
public :
	typedef dw::system::Buffer super;

	enum types
	{
		type_vertex = 0,	// glBindBuffer(GL_ARRAY_BUFFER , ...)
		type_index,		// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ...)
		// type_pixel,
		// type_uniform,
		// type_command,	// glBind(GL_DRAW_INDIRECT_BUFFER, ...) see glDrawElementsIndirect // permet de binder un buffer de commands !!

		types_count
	};

	enum updates
	{
		update_never = 0,
		update_sometimes,
		update_often,

		updates_count
	};

	enum usages
	{
		usage_draw = 0,
		usage_read,
		usage_copy,

		usages_count
	};

public :
	void resize(uint32 elementsCount);

	void bind();
	void unbind();

	void* map(accesses access, uint32 elementOffset = 0);
	void unmap();

	void read(void* data) const ;
	void read(void* data, uint32 elementOffset, uint32 elementsCount) const ;

	void write(const void* data);
	void write(const void* data, uint32 elementOffset, uint32 elementsCount);

public :
	bool isValid() const ;
	bool isBound() const ;
	bool isMapped() const ;

	uint32 getSize() const ;
	uint32 getCount() const ;
	uint32 getElementSize() const ;

protected :
	BufferObject(types type, updates update, usages usage);
	BufferObject(GLuint id, types type, updates update, usages usage);
	~BufferObject();

protected :
	void setElementSize(uint32 size);

private :
	static GLenum glTarget(types type);
	static GLenum glBinding(types type);
	static GLenum glAccess(accesses access);
	static GLenum glUsage(updates update, usages usage);

private :
	static const GLenum glUsages[];
	static const GLenum glTargets[types_count];
	static const GLenum glBindings[types_count];
	static const GLenum glAccesses[accesses_count];

	GLenum m_target;
	GLenum m_binding;
	GLenum m_usage; //! @todo refactor this : glUsage may be different for some operations
	const bool m_managed;
	GLuint m_id;
	uint32 m_elementSize;
};

		} // namespace details
	} // namespace graphics
} // namespace dw

#include "graphics/opengl/bufferobject.inl"

#endif // !DW_GRAPHICS_OPENGL_BUFFER_OBJECT_H
